package android.content;

import io.reactivex.annotations.NonNull;
import io.reactivex.annotations.Nullable;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author slc
 * @date 2022/03/29 上午 11:19
 */
public class Intent {
    public static final String ACTION_BOOT_COMPLETED = "android.intent.action.ACTION_BOOT_COMPLETED";
    public static final String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
    public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
    public static final String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT";
    public static final String ACTION_MAIN = "android.intent.action.MAIN";
    public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 0x00400000;
    private String mAction;
    private String mPackage;
    private ComponentName mComponent;
    private Map<String, Object> mExtras;
    private int mFlags;

    public Intent() {

    }

    public Intent(String action) {
        this.mAction = action;
    }

    public Intent(Context context, Class<? extends Context> targetContext) {
        this.mPackage = context.getPackageName();
        this.mComponent = new ComponentName(this.mPackage, targetContext.getName());
    }

    public Intent(Context context, String targetContextName) {
        this.mPackage = context.getPackageName();
        this.mComponent = new ComponentName(this.mPackage, targetContextName);
    }

    public String getAction() {
        return mAction;
    }

    public Intent setAction(String action) {
        this.mAction = action;
        return this;
    }

    public Intent setPackage(String mPackage) {
        this.mPackage = mPackage;
        return this;
    }

    public String getPackage() {
        return mPackage;
    }

    public Intent setComponent(ComponentName mComponent) {
        this.mComponent = mComponent;
        return this;
    }

    public @Nullable
    ComponentName getComponent() {
        return mComponent;
    }


    public Map<String, Object> getExtras() {
        return mExtras;
    }

    public void setExtras(Map<String, Object> mExtras) {
        this.mExtras = mExtras;
    }

    public boolean getBooleanExtra(String name, boolean defaultValue) {
        return mExtras == null ? defaultValue :
                (boolean) mExtras.getOrDefault(name, defaultValue);
    }

    public byte getByteExtra(String name, byte defaultValue) {
        return mExtras == null ? defaultValue :
                (byte) mExtras.getOrDefault(name, defaultValue);
    }

    public short getShortExtra(String name, short defaultValue) {
        return mExtras == null ? defaultValue :
                (short) mExtras.getOrDefault(name, defaultValue);
    }

    public char getCharExtra(String name, char defaultValue) {
        return mExtras == null ? defaultValue :
                (char) mExtras.getOrDefault(name, defaultValue);
    }

    public int getIntExtra(String name, int defaultValue) {
        return mExtras == null ? defaultValue :
                (int) mExtras.getOrDefault(name, defaultValue);
    }

    public long getLongExtra(String name, long defaultValue) {
        return mExtras == null ? defaultValue :
                (long) mExtras.getOrDefault(name, defaultValue);
    }


    public float getFloatExtra(String name, float defaultValue) {
        return mExtras == null ? defaultValue :
                (float) mExtras.getOrDefault(name, defaultValue);
    }

    public double getDoubleExtra(String name, double defaultValue) {
        return mExtras == null ? defaultValue :
                (double) mExtras.getOrDefault(name, defaultValue);
    }

    public @Nullable
    String getStringExtra(String name) {
        return mExtras == null ? null : (String) mExtras.get(name);
    }

    public @Nullable
    CharSequence getCharSequenceExtra(String name) {
        return mExtras == null ? null : (CharSequence) mExtras.get(name);
    }

    public @Nullable
    Serializable getSerializableExtra(String name) {
        return mExtras == null ? null : (Serializable) mExtras.get(name);
    }

    public @Nullable
    ArrayList<Integer> getIntegerArrayListExtra(String name) {
        return mExtras == null ? null : (ArrayList<Integer>) mExtras.get(name);
    }

    public @Nullable
    ArrayList<String> getStringArrayListExtra(String name) {
        return mExtras == null ? null : (ArrayList<String>) mExtras.get(name);
    }

    public @Nullable
    ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) {
        return mExtras == null ? null : (ArrayList<CharSequence>) mExtras.get(name);
    }

    public @Nullable
    boolean[] getBooleanArrayExtra(String name) {
        return mExtras == null ? null : (boolean[]) mExtras.get(name);
    }

    public @Nullable
    byte[] getByteArrayExtra(String name) {
        return mExtras == null ? null : (byte[]) mExtras.get(name);
    }

    public @Nullable
    short[] getShortArrayExtra(String name) {
        return mExtras == null ? null : (short[]) mExtras.get(name);
    }

    public @Nullable
    char[] getCharArrayExtra(String name) {
        return mExtras == null ? null : (char[]) mExtras.get(name);
    }

    public @Nullable
    int[] getIntArrayExtra(String name) {
        return mExtras == null ? null : (int[]) mExtras.get(name);
    }

    public @Nullable
    long[] getLongArrayExtra(String name) {
        return mExtras == null ? null : (long[]) mExtras.get(name);
    }

    public @Nullable
    float[] getFloatArrayExtra(String name) {
        return mExtras == null ? null : (float[]) mExtras.get(name);
    }

    public @Nullable
    double[] getDoubleArrayExtra(String name) {
        return mExtras == null ? null : (double[]) mExtras.get(name);
    }

    public @Nullable
    String[] getStringArrayExtra(String name) {
        return mExtras == null ? null : (String[]) mExtras.get(name);
    }

    public @Nullable
    CharSequence[] getCharSequenceArrayExtra(String name) {
        return mExtras == null ? null : (CharSequence[]) mExtras.get(name);
    }

    public @Nullable
    Map<String, Object> getBundleExtra(String name) {
        return mExtras == null ? null : (Map<String, Object>) mExtras.get(name);
    }

    private void ensureExtras() {
        if (mExtras == null) {
            mExtras = new HashMap<>();
        }
    }

    public @NonNull
    Intent putExtra(String name, boolean value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, byte value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, char value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, short value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, int value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, long value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }


    public @NonNull
    Intent putExtra(String name, float value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, double value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable String value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable CharSequence value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putIntegerArrayListExtra(String name,
                                    @Nullable ArrayList<Integer> value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putStringArrayListExtra(String name, @Nullable ArrayList<String> value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putCharSequenceArrayListExtra(String name,
                                         @Nullable ArrayList<CharSequence> value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable Serializable value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable boolean[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable byte[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable short[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }


    public @NonNull
    Intent putExtra(String name, @Nullable char[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable int[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable long[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable float[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable double[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }


    public @NonNull
    Intent putExtra(String name, @Nullable String[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }

    public @NonNull
    Intent putExtra(String name, @Nullable CharSequence[] value) {
        ensureExtras();
        mExtras.put(name, value);
        return this;
    }


    public @NonNull
    Intent putExtra(String name, @Nullable Map<String, Object> value) {
        ensureExtras();
        mExtras.putAll(value);
        return this;
    }


    public @NonNull
    Intent putExtras(@NonNull Intent src) {
        if (src.mExtras != null) {
            if (mExtras == null) {
                ensureExtras();
            } else {
                mExtras.putAll(src.mExtras);
            }
        }
        return this;
    }

    public @NonNull
    Intent putExtras(@NonNull Map<String, Object> value) {
        ensureExtras();
        mExtras.putAll(value);
        return this;
    }

    public @NonNull Intent setFlags(int flags) {
        mFlags = flags;
        return this;
    }

    public @NonNull Intent addFlags(int flags) {
        mFlags |= flags;
        return this;
    }

    public void removeFlags(int flags) {
        mFlags &= ~flags;
    }
}
